package com.xhui.vimarket.zkplus.ui.id;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.zkoss.web.fn.ServletFns;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.Sessions;
import org.zkoss.zk.ui.http.DHtmlLayoutServlet;
import org.zkoss.zk.ui.metainfo.ComponentInfo;
import org.zkoss.zk.ui.sys.DesktopCache;
import org.zkoss.zk.ui.sys.WebAppCtrl;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Style;

import com.xhui.vimarket.common.utils.string.StrUtil;

public class GrinderIdGenerator extends DHtmlLayoutServlet implements
       org.zkoss.zk.ui.sys.IdGenerator {
    /**
     * 会话桌面数量属性。
     */
    private final static String SESSION_DESKTOP_COUNT = "SESSION_DESKTOP_COUNT";
    /**
     * 桌面会话属性。
     */
    private final static String COMMON_DESKTOP_PART = "COMMON_DESKTOP_PART";
    /**
     * 增量器。
     */
    private static AtomicInteger _desktop = new AtomicInteger();
    /**
     * 线程页面。
     */
    private static ThreadLocal _page = new ThreadLocal();
    /**
     * 。
     */
    private static ThreadLocal _response = new ThreadLocal();
    /**
     * 
     * {@inheritDoc}
     * @see org.zkoss.zk.ui.http.DHtmlLayoutServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     * @author zhoupc
     * 2011-5-10 zhoupc
     */
    protected void doGet(HttpServletRequest request,
           HttpServletResponse response) throws ServletException, IOException {
       _response.set(response);// soon to be used...
       super.doGet(request, response);
    }
    /**
     * 
     * 替换非数字和字母字符。
     * 
     * @param input
     * @return
     * @author zhoupc
     * 2011-5-10 zhoupc
     */
    protected String removeChars(String input) {
        Pattern pattern = Pattern.compile("[^0-9a-zA-Z_]");
        Matcher matcher = pattern.matcher(input);
        return matcher.replaceAll("");
    }
    /**
     * 
     * 获取组件标识.
     * 
     * @param component 组件
     * @return 组件可能标识。
     * @author zhoupc
     * 2011-5-10 zhoupc
     */
    public String getIdPartFromParent(Component component) {
        StringBuffer result = new StringBuffer();
        Component c = component;
        int index = 2;
        while (c.getParent() != null && !(c.getParent() instanceof Page)) {
            if (!StrUtil.isNullOrEmpty(c.getParent().getId())) {
                result.append(c.getParent().getId());
                result.append("_");
                index--;
            }
            if (index == 0) {
                break;
            }
            c = c.getParent();
        }
        return result.toString();
    }
    /**
     * 
     * {@inheritDoc}
     * @see org.zkoss.zk.ui.sys.IdGenerator#nextComponentUuid(org.zkoss.zk.ui.Desktop, org.zkoss.zk.ui.Component)
     * @author zhoupc
     * 2011-5-10 zhoupc
     */
    public String nextComponentUuid(Desktop desktop, Component component) {
           String pageURI = "";
           if (component.getPage() != null && component.getPage().getUuid() != null) {
               pageURI = component.getPage().getUuid();
           } else {
               Page page = (Page) desktop.getPages().toArray()[0];
               HttpServletRequest hsr = (HttpServletRequest) page.getDesktop()
                  .getExecution().getNativeRequest();
               pageURI = hsr.getRequestURI();
               pageURI = removeChars(pageURI);               
           }
           String componentId = component.getId();
           String compid = null;
           if (StrUtil.isNullOrEmpty(componentId)) {
               String attrValue = (String)component.getAttribute(ZKRebuildUuid.CRM2ID);
               if (!StrUtil.isNullOrEmpty(attrValue)) {
                   componentId = attrValue; 
                   //移除属性。
                   component.removeAttribute(ZKRebuildUuid.CRM2ID);
               } 
               if (component instanceof Listitem && StrUtil.isNullOrEmpty(componentId)) {
                   if (component.getParent() != null) {
                       componentId = component.getParent().getId() + "_li";
                   }
               }
               if (component instanceof Style && StrUtil.isNullOrEmpty(componentId)) {
                   componentId = "style";
               }
           }
           if (componentId != null && !"".equals(componentId)) {
               compid = "__ID__" + pageURI + "_" + component.getClass().getSimpleName()
                + getIdPartFromParent(component) + "_" + componentId;// 09-11-18 
               //compid计算算法修改。
               /*if ("__ID__webappmod_ordersaleoffer_order_navzul_Textboxdefbox_qryform__key".equals(compid)
                   || "__ID__webappmod_ordersaleoffer_order_navzul_ToolbarbuttonqueryProdInstEtx_prodInstPopup__btnQuery".equals(compid)
                   || "__ID__webappmod_ordersaleoffer_order_navzul_ListboxprodListbox_queryProdInstEtx__listbox".equals(compid)
                   || "__ID__webappmod_ordersaleoffer_order_navzul_Buttonbtnbar_queryProdInstEtx__btnSubmit".equals(compid)) {
                   String cls = "";
                   Component c = component;
                   while (c != null) {
                       cls = c.getClass().getSimpleName() + "_" + cls;
                       c = c.getParent();
                   }
                   //System.out.println(cls);
                   //System.out.println(calcCompid);
                   compid =compid + cls;
               }*/
               int index = 0;
               String calcCompid = compid;
               while (desktop.getComponentByUuidIfAny(calcCompid) != null)
               {
                   calcCompid = compid + "_ADD_" + index;
                   index++;
               }
               compid = calcCompid;
               /*if (desktop.getComponentByUuidIfAny(compid) != null) {
                   Long pageIDCount = (Long)desktop.getAttribute(compid);
                   if (pageIDCount == null) {
                       pageIDCount = 0L;
                   }
                   pageIDCount++;
                   desktop.setAttribute(compid, pageIDCount);
                   compid = compid + "_ADD_" +   (pageIDCount - 1 );// 09-11-18
                   

               } else {
                   Long pageIDCount = (Long)desktop.getAttribute(compid);
                   if (pageIDCount != null) {
                       desktop.removeAttribute(compid);
                   }
               }*/
           } else {
               String crmPageURI = "CRM_2_" + pageURI;
               Long pageURICount = (Long)desktop.getAttribute(crmPageURI);
               if (pageURICount == null) {
                   pageURICount = 0L;
               }         
              compid = "_AUTO_"+ pageURI + "_" + component.getClass().getSimpleName()
               + "_" + pageURICount;// 09-11-18
              pageURICount++;
              desktop.setAttribute(crmPageURI, pageURICount);
           }
           return compid;
    }
    /**
     * 
     * {@inheritDoc}
     * @see org.zkoss.zk.ui.sys.IdGenerator#nextPageUuid(org.zkoss.zk.ui.Page)
     * @author zhoupc
     * 2011-5-10 zhoupc
     */
    public String nextPageUuid(Page page) {
       HttpServletRequest hsr = (HttpServletRequest) page.getDesktop()
              .getExecution().getNativeRequest();
       _page.set(new AtomicInteger());// not really needed since is threadlocal    
       String result = hsr.getRequestURI();
       result = removeChars(result);
       if (page.getDesktop() != null) {
           page.getDesktop().setAttribute("CRM_2_" + result, 0L);
       }  
       try {
           HttpServletResponse response = (HttpServletResponse) _response.get();
           if (!response.containsHeader("JsPath")) {
               response.addHeader("JsPath", ServletFns.encodeURL("~./js/zul.lang.wpd")); 
               response.addHeader("PngPath", ServletFns.encodeURL("~./zul/img/tab/tabs-v-bg.png")); 
           }
       } catch (ServletException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }      
       return result;
    }
    /**
     * 
     * 获取dtid算法.
     * 
     * @param desktopCache 桌面缓存。
     * @param dtid         宿主dtid。
     * @return String dtid.
     * @author zhoupc
     * 2011-5-19 zhoupc
     */
    public String getDtid(DesktopCache desktopCache, String dtid) {
        int i = 0;
        String result = dtid;
        while (desktopCache.getDesktopIfAny(result) != null) {
            result = dtid  + "_ADD_" +   i;
            i++;
        }
        return result;
        
    }
    /**
     * 
     * {@inheritDoc}
     * @see org.zkoss.zk.ui.sys.IdGenerator#nextDesktopId(org.zkoss.zk.ui.Desktop)
     * @author zhoupc
     * 2011-5-10 zhoupc
     */
    public String nextDesktopId(Desktop desktop) {
        String dtid = null;
        String commonPart = "";
        HttpServletResponse response = (HttpServletResponse) _response.get();
        if (Sessions.getCurrent() != null && Sessions.getCurrent().getNativeSession() != null) {
            HttpSession session = (HttpSession) Sessions.getCurrent().getNativeSession();
            commonPart = (String) session.getAttribute(COMMON_DESKTOP_PART); 
            if (commonPart == null) {
                commonPart = "" + _desktop.getAndIncrement();
                session.setAttribute(COMMON_DESKTOP_PART, commonPart);
            }
            HttpServletRequest hsr = (HttpServletRequest) desktop.getExecution().getNativeRequest(); 
            String uri = hsr.getRequestURI();
            
            uri = removeChars(uri);
            dtid = "Desktop_" + commonPart + "_Desktop" + uri;

            WebAppCtrl webapp = (WebAppCtrl) desktop.getWebApp();
            DesktopCache desktopCache = webapp.getDesktopCache(desktop.getSession());
            dtid = getDtid(desktopCache, dtid); 
            response.addHeader(uri, "__" + uri + "__" + dtid + "__" + uri + "__");
        } else {
            dtid = "Desktop_" + _desktop.getAndIncrement(); 
        }
        
        response.addHeader("Desktop", dtid); // ...and here it is!      
        return dtid;
    }
	@Override
	public String nextComponentUuid(Desktop desktop, Component comp,
			ComponentInfo compInfo) {
		// TODO Auto-generated method stub
		return null;
	}
}
